home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / listserv / sco / mmdf-listserv / src / mmdfcatmail.c next >
Encoding:
C/C++ Source or Header  |  1993-02-28  |  6.0 KB  |  239 lines

  1. /*
  2.  *                              mmdfcatmail.c
  3.  *
  4.  *  Due to the behavior of MMDF (at least on SCO Unix), we can't use
  5.  * listserv's /usr/server/catmail program within an aliased pipe.  MMDF strips
  6.  * the first "From  " line in pipes, which listserv requires.  It would
  7.  * probably be best if listserv always used the From: or Sender: rfc822 header.
  8.  *
  9.  * This program is a frontend to catmail.  It reads ahead in a mail stream and
  10.  * picks the sender's address from the rfc822 header and assembles a fake
  11.  * "From addr date" line and sends the whole mess to catmail.  All command line
  12.  * arguments are passed directly to catmail.
  13.  *
  14.  *  To use this facility with MMDF, add lines such as this to your
  15.  * /usr/mmdf/table/alias.list:
  16.  *
  17.  *  listserv: server|/usr/server/mmdfcatmail -r -f
  18.  *  somelist: server|/usr/server/mmdfcatmail -L SOMELIST -f
  19.  *
  20.  * Note that your /usr/mmdf/mmdftailor file must have the "trusted" keyword
  21.  * in the ALIAS entry for the alias.list file or pipes will not work:
  22.  *
  23.  *    ALIAS     table=lalias,   nobypass,       trusted 
  24.  *
  25.  * Here is the don't sue me copyright:
  26.  *
  27.  * Copyright 1993 Mark Diekhans (markd@grizzly.com)
  28.  * Permission to use, copy, modify, and distribute this software and its
  29.  * documentation for any purpose and without fee is hereby granted, provided
  30.  * that the above copyright notice appear in all copies.  Mark Diekhans makes
  31.  * no representations about the suitability of this software for any purpose.
  32.  * It is provided "as is" without express or implied warranty.
  33.  */
  34.  
  35.  
  36. #include <stdio.h>
  37. #include <unistd.h>
  38. #include <string.h>
  39. #include <ctype.h>
  40. #include <sys/types.h>
  41. #include <sys/wait.h>
  42.  
  43. #include "defs.h"
  44. #include "struct.h"
  45. #include "global.h"
  46.  
  47. BOOLEAN tty_echo = FALSE; /* -e option off */
  48. FILE *report      = NULL; /* Progress report to the administrator */
  49.  
  50. extern void extract_address (char *);
  51.  
  52. #define CATMAIL   "/usr/server/catmail"
  53.  
  54. /*
  55.  * Maximum number of lines to read looking for "From:" or "Sender:".
  56.  */
  57. #define MAX_HEADER_LINES  2048
  58.  
  59. /*
  60.  * Type used to save header fields in memory.  Also structure used to
  61.  * keep a list of these header lines.
  62.  */
  63. typedef struct strEntry_t {
  64.     struct strEntry_t *next;
  65.     char               line [1];  /* MUST BE LAST FIELD. */
  66. } strEntry_t;
  67.  
  68. typedef struct {
  69.     strEntry_t  *head;
  70.     strEntry_t  *tail;
  71. } strList_t;
  72.  
  73. /*
  74.  * Save a line away in a dynamically allocated structure and added that
  75.  * structure to a list.
  76.  */
  77.  
  78. void
  79. SaveLine (const char  *line,
  80.           strList_t   *list)
  81. {
  82.     strEntry_t *entry;
  83.  
  84.     entry = (strEntry_t *) malloc (sizeof (strEntry_t) + (strlen (line)));
  85.     strcpy (entry->line, line);
  86.     entry->next = NULL;
  87.  
  88.     if (list->tail == NULL) {
  89.         list->head = entry;
  90.     } else {
  91.         list->tail->next = entry;
  92.     }
  93.     list->tail = entry;
  94. }
  95.  
  96. /*
  97.  * Start the catmail process.  
  98.  */
  99. pid_t
  100. StartCatmail (const char **argv,
  101.               FILE       **toPipe)
  102. {
  103.     int    pipefds [2];
  104.     pid_t  pid;
  105.  
  106.     *toPipe = NULL;
  107.  
  108.     if (pipe (pipefds) == 0) {
  109.         *toPipe = fdopen (pipefds [1], "w");
  110.     }
  111.     if (*toPipe == NULL) {
  112.         fprintf (stderr, "open of pipe failed: %s", strerror (errno));
  113.         exit (1);
  114.     }
  115.  
  116.     pid = fork ();
  117.     if (pid < 0) {
  118.         fprintf (stderr, "fork failed: %s", strerror (errno));
  119.         exit (1);
  120.     }
  121.     if (pid > 0) {
  122.         close (pipefds [0]);
  123.         return pid;
  124.     }
  125.  
  126.     close (pipefds [1]);
  127.     close (STDIN_FILENO);
  128.     if (dup2 (pipefds [0], STDIN_FILENO) < 0) {
  129.         fprintf (stderr, "dup to stdin failed: %s", strerror (errno));
  130.         exit (1);
  131.     }
  132.  
  133.     argv [0] = strrchr (CATMAIL, '/');
  134.     if (argv [0] == NULL)
  135.         argv [0] = CATMAIL;
  136.     execv (CATMAIL, argv);
  137.     
  138.     fprintf (stderr, "exec of %s failed: %s", CATMAIL, strerror (errno));
  139.     exit (1);
  140. }
  141.  
  142. /*
  143.  * Do actual work of copying stdin catmail process, filling in the missing
  144.  * "From address Date" line.
  145.  */
  146. main (int          argc,
  147.       const char **argv)
  148. {
  149.     strList_t    headerList;
  150.     strEntry_t  *entry;
  151.     char         line [MAX_LINE + 1];
  152.     char         fromAddress [MAX_LINE];
  153.     char         date [MAX_LINE];
  154.     int          linesRead = 0, waitStat;
  155.     pid_t        pid;
  156.     FILE        *toPipe;
  157.  
  158.     headerList.head = NULL;
  159.     headerList.tail = NULL;
  160.     fromAddress [0] = '\0';
  161.     date [0] = '\0';
  162.  
  163.     /*
  164.      * Search for the minimum headers we need and save away lines for later
  165.      * output.
  166.      */
  167.     while (! ((fromAddress [0] != '\0') && (date [0] != '\0'))) {
  168.         if (fgets (line, MAX_LINE, stdin) == NULL)
  169.             break;
  170.  
  171.         SaveLine (line, &headerList);
  172.  
  173.         if (strncmp (line, "From:", 5) == 0) {
  174.             strcpy (fromAddress, line + 5); 
  175.             extract_address (fromAddress);
  176.             continue;
  177.         }
  178.         if (strncmp (line, "Sender:", 6) == 0) {
  179.             strcpy (fromAddress, line + 6); 
  180.             extract_address (fromAddress);
  181.             continue;
  182.         }
  183.         if (strncmp (line, "Date:", 5) == 0) {
  184.             strcpy (date, line + 6); 
  185.             continue;
  186.         }
  187.         linesRead++;
  188.         if (linesRead > MAX_HEADER_LINES)
  189.             break;
  190.     }
  191.     if (fromAddress [0] == '\0') {
  192.         fprintf (stderr, "No \"From:\" or \"Sender:\" header found\n");
  193.         exit (1);
  194.     }
  195.     if (date [0] == '\0') {
  196.         fprintf (stderr, "No \"date:\" header found\n");
  197.         exit (1);
  198.     }
  199.  
  200.     pid = StartCatmail (argv, &toPipe);
  201.  
  202.     /*
  203.      * Output our madeup from line. (date has "\n").
  204.      */
  205.     fprintf (toPipe, "From %s %s", fromAddress, date);
  206.  
  207.     entry = headerList.head;
  208.     while (entry != NULL) {
  209.         fputs (entry->line, toPipe);
  210.         entry = entry->next;
  211.     }
  212.  
  213.     while (fgets (line, MAX_LINE, stdin) != NULL)
  214.         fputs (line, toPipe);
  215.  
  216.     fclose (toPipe);
  217.  
  218.     if (waitpid (pid, &waitStat, 0) < 0) {
  219.         fprintf (stderr, "waitpid failed: %s", strerror (errno));
  220.         exit (1);
  221.     }
  222.  
  223.     if (WIFEXITED (waitStat))
  224.         exit (WEXITSTATUS (waitStat));
  225.  
  226.     fprintf (stderr, "%s terminated for unknown reasons\n", CATMAIL);
  227.     exit (1);
  228.  
  229. }
  230.  
  231. /*
  232.  * The library needs this guy.
  233.  */
  234. int
  235. gexit (int exitcode)
  236. {
  237.     exit (exitcode);
  238. }
  239.